﻿using NCM_MSTest.Alg;

namespace NCM_MSTest.Test
{
    [TestClass]
    [TestCategory("插值测试")]
    public class 插值测试
    {
        [TestMethod("n阶拉格朗日差值计算测试")]
        [DataRow(
            new double[] { -2, -0.4, -0.2, 1, 4 }
          , new double[] { 24, -0.2688, -0.0766, 0, 480 }
          , new double[] { -1.5, -1, -0.2, 0, 0.4, 0.8, 1.5, 2.0 }
          , new double[] { 5.6242, -0.00066138, -0.0766, 0.00035273, -0.26834, -0.46056, 5.6241, 23.9979 }
          )]
        public void Example_2_2(double[] x, double[] y, double[] x1, double[] y1)
        {
            int n = x.Length;
            int m = x1.Length;
            double[] ry1 = new double[m];
            Interpolation.LagrangeN(n, x, y, m, x1, ref ry1);
            System.Diagnostics.Trace.WriteLine($"x1\ty1\ty1\tDelta");
            for (int i = 0; i < m; i++)
            {
                System.Diagnostics.Trace.WriteLine($"{x1[i]:f5}  {y1[i]:f5}  {ry1[i]:f5}  {y1[i] - ry1[i]:f5}");
                Assert.IsTrue(ry1[i].EqualsEx(y1[i]));
            }
        }

        [TestMethod("分段差值测试")]
        [DataRow(
            new double[] { 0.0, 0.10, 0.195, 0.30, 0.401, 0.50 }
            , new double[] { 0.39894, 0.39695, 0.39142, 0.38138, 0.36812, 0.35206 }
            , new double[] { 0.15, 0.30, 0.45 }
            , new double[] { 0.39404, 0.381380, 0.36017 }
            , new double[] { 0.394460, 0.381380, 0.360550 }
            )]
        public void Example_2_3(double[] x, double[] y, double[] x1, double[] y1, double[] y2)
        {
            double[] ry0 = new double[x1.Length];
            double[] ry1 = new double[x1.Length];
            double[] ry2 = new double[x1.Length];
            int n = x.Length;
            int m = x1.Length;
            PicewiseInterpolation.LinearInterp(n, x, y, m, x1, ref ry0);
            PicewiseInterpolation.ThreeInterpA(n, x, y, m, x1, ref ry1);
            PicewiseInterpolation.ThreeInterpB(n, x, y, m, x1, ref ry2);

            System.Diagnostics.Trace.WriteLine("分段线性插值");
            System.Diagnostics.Trace.WriteLine("x1 \t y1 \t ry \t Delta");
            for (int i = 0; i < m; i++)
            {
                System.Diagnostics.Trace.WriteLine($"{x1[i]:f5}  {y1[i]:f5}  {ry0[i]:f5}  {y1[i] - ry0[i]:f5}");
            }
            System.Diagnostics.Trace.WriteLine("分段一元三点插值");
            System.Diagnostics.Trace.WriteLine("   x1 \t y2 \t ry \t Delta");
            for (int i = 0; i < m; i++)
            {
                System.Diagnostics.Trace.WriteLine($"A: {x1[i]:f5}  {y2[i]:f5}  {ry1[i]:f5}  {y2[i] - ry1[i]:f5}");
                System.Diagnostics.Trace.WriteLine($"B: {x1[i]:f5}  {y2[i]:f5}  {ry2[i]:f5}  {y2[i] - ry2[i]:f5}");
            }
            for (int i = 0; i < m; i++)
            {
                Assert.IsTrue(y1[i].EqualsEx(ry0[i]));
                Assert.IsTrue(y2[i].EqualsEx(ry1[i]));
                Assert.IsTrue(y2[i].EqualsEx(ry2[i]));
            }
        }


        private static double[,] Ex_2_4 = new double[4, 3]
        {
            {0.43674,0.61193,0.78756 }
            ,{0.43973,0.62003,0.80437 }
            ,{0.44455,0.63364,0.83431 }
            ,{0.44901,0.64707,0.86653 }
        };

        private static double[] Ex_2_4_Line_R = new double[]
        {
            0.53449,0.52711,0.74539
        };

        private static double[] Ex_2_4_TwiceThree_R = new double[]
        {
            0.53358,0.52643,0.74323
        };

        [TestMethod("二元函数插值")]
        [DataRow(
            new double[] { 10, 30, 50, 70 }
            , new double[] { 25, 35, 45 }
            , new double[] { 40, 20, 60 }
            , new double[] { 30, 30, 40 }
            )]
        public void Example_2_4(double[] x, double[] y, double[] xi, double[] yi)
        {
            int n = x.Length;
            int m = y.Length;
            double[,] f = Ex_2_4;
            int k = xi.Length;
            double[] fi_l = Ex_2_4_Line_R;
            double[] fi_t = Ex_2_4_TwiceThree_R;
            double[] fi0 = new double[k];
            double[] fi1 = new double[k];
            for (int k1 = 0; k1 < k; k1++)
            {
                BinaryFunctionInterpolation.LinearIntrp(n, m, x, y, f, xi[k1], yi[k1], ref fi0[k1]);
                BinaryFunctionInterpolation.TwiceThreePointIntrp(n, m, x, y, f, xi[k1], yi[k1], ref fi1[k1]);
            }
            System.Diagnostics.Trace.WriteLine("二元分段线性插值");
            System.Diagnostics.Trace.WriteLine($"xi \t yi \t fi \t rfi \t Delta");
            for (int i = 0; i < k; i++)
            {
                System.Diagnostics.Trace.WriteLine($"{xi[i]:f6} \t {yi[i]:f6} \t {fi_l[i]:f6} \t {fi0[i]:f6} \t {fi_l[i] - fi0[i]:f6}");
            }
            System.Diagnostics.Trace.WriteLine("二元分段三点插值");
            System.Diagnostics.Trace.WriteLine($"xi \t yi \t fi \t rfi \t Delta");
            for (int i = 0; i < k; i++)
            {
                System.Diagnostics.Trace.WriteLine($"{xi[i]:f6} \t {yi[i]:f6} \t {fi_t[i]:f6} \t {fi1[i]:f6} \t {fi_t[i] - fi1[i]:f6}");
            }
            for (int i = 0; i < k; i++)
            {
                Assert.IsTrue(fi_l[i].EqualsEx(fi0[i]));
            }
            for (int i = 0; i < k; i++)
            {
                Assert.IsTrue(fi_t[i].EqualsEx(fi1[i]));
            }
        }

    }
}
